from fastapi import APIRouter, HTTPException
from config import WORK_CASH_GIVE
from utils.funcs import get_current_date
from utils.models.user import MAX_LEN_NAME as USER_MAX_LEN_NAME
from api.dep import auth_dep, uow_dep
from api.schemas import EditNameInfo, GiveCashInfo
from api.dto import (generate_sqlalchemy_dto, generate_many_sqlalchemy_dto,
                     UsersMeDTO, UsersOtherDTO)

router = APIRouter(prefix="/users", tags=["users"])


@router.get("/me/")
async def me(token=auth_dep, uow=uow_dep):
    user = await uow.users.check_auth_and_get(token)

    return generate_sqlalchemy_dto(UsersMeDTO, user)


@router.get("/get_user/{user_id}")
async def get_user(user_id: int, token=auth_dep, uow=uow_dep):
    await uow.users.check_auth_and_get(token)
    user = await uow.users.select_by_id(user_id)

    if user is None:
        raise HTTPException(status_code=404,
                            detail="Юзер не найден")

    return generate_sqlalchemy_dto(UsersOtherDTO, user)


@router.get("/get_all_users")
async def get_all_users(token=auth_dep, uow=uow_dep):
    await uow.users.check_auth_and_get(token)

    users = await uow.users.select_all()

    return generate_many_sqlalchemy_dto(UsersOtherDTO, users)


@router.get("/get_region_users/{region_id}")
async def get_region_users(region_id: int, token=auth_dep, uow=uow_dep):
    await uow.users.check_auth_and_get(token)

    users = await uow.users.select_by_residence(region_id)

    return generate_sqlalchemy_dto(UsersOtherDTO, users) or None


@router.post("/edit_name/")
async def edit_name(info: EditNameInfo, token=auth_dep, uow=uow_dep):
    user = await uow.users.check_auth_and_get(token)

    if len(info.name.replace(' ', '')) == 0:
        raise HTTPException(status_code=400,
                            detail="Нельзя делать пустое имя")

    if len(info.name) > USER_MAX_LEN_NAME:
        raise HTTPException(status_code=400,
                            detail="Слишком длинное имя")

    await uow.users.edit_name(user.id, info.name)

    return "ok"


@router.post("/work/")
async def work(token=auth_dep, uow=uow_dep):
    user = await uow.users.check_auth_and_get(token)
    region = await uow.regions.select_by_id(user.residence)
    state = await uow.states.select_by_id(region.state_id)

    if region.gold <= 0:
        raise HTTPException(status_code=400,
                            detail="В регионе недостаточно золота")

    if user.work_end > get_current_date():
        raise HTTPException(status_code=400,
                            detail="Вы не можете сейчас работать")

    # find min of strength and education
    a = min((user.strength, user.education))

    if state is not None:
        state_reward = (state.taxes / 100) * a * WORK_CASH_GIVE
    else:
        state_reward = 0

    user_reward = a * WORK_CASH_GIVE - state_reward

    await uow.regions.remove_one_gold(region.id)
    await uow.users.set_sleep_work(user.id)
    await uow.users.add_cash(user.id, user_reward)

    if state is not None:
        await uow.states.add_cash(state.id, state_reward)

    return {"user_reward": user_reward,
            "state_reward": state_reward}


@router.post("/give_cash")
async def give_cash(info: GiveCashInfo, token=auth_dep, uow=uow_dep):
    user = await uow.users.check_auth_and_get(token)
    target = await uow.users.select_by_id(info.user_id)

    if target is None:
        raise HTTPException(status_code=404,
                            detail="Пользователь не найден")

    if user.cash < info.amount:
        raise HTTPException(status_code=400,
                            detail="Недостаточно денег")

    if info.amount <= 0:
        raise HTTPException(status_code=403,
                            detail="Число должно быть больше 0")

    await uow.users.give_cash(user.id, target.id, info.amount)

    return "ok"
